home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 26 / CU Amiga Magazine's Super CD-ROM 26 (1998)(EMAP Images)(GB)[!][issue 1998-09].iso / CUCD / PowerPC / uae-0.8.4 / docs / README.PROGRAMMERS < prev   
Text File  |  1998-05-11  |  16KB  |  304 lines

  1. You can help to make this program better. If you fix bugs or implement new
  2. features, I'd be grateful if you send me patches. For a list of interesting
  3. projects, and for a brief summary on how UAE works, see below.
  4.  
  5. A few guidelines for anyone who wants to help:
  6. - Please contact me first before you implement major new features. Someone 
  7.   else might be doing the same thing already. This has already happened :-(
  8.   Even if no one else is working on this feature, there might be alternative
  9.   and better/easier/more elegant ways to do it.
  10. - If you have more than one Kickstart, try your code with each one.
  11. - Patches are welcome in any form, but diff -u or diff -c output is preferred.
  12.   If I get whole source files, the first thing I do is to run diff on it. You 
  13.   can save me some work here (and make my mailbox smaller).
  14.  
  15. Some possible projects, in order of estimated difficulty:
  16. - Add gamma correction
  17. - If the serial port still isn't working (I've got no idea, I don't use it),
  18.   fix it.
  19. - Someone with a 68020 data sheet might check whether all opcodes are
  20.   decoded correctly and whether all instructions really do what they are 
  21.   supposed to do (I'm pretty sure it's OK by now, but you never know...).
  22. - Add more 2.0 packets to filesys.c
  23. - Multi-thread support is there now, it just needs someone to test it on a SMP
  24.   machine and to fix it so it improves speed instead of slowing the thing 
  25.   down.
  26. - Improve the Kickstart replacement to boot more demos.
  27. - Snapshots as in CPE. Will need to collect all the variables containing
  28.   important information. Fairly easy, but boring. (Use core dumps instead :-)
  29.   _If_ someone attempts this, please be more clever than the various CPC
  30.   emulators and dump state only at one fixed point in the frame, preferrably
  31.   the vsync point. Also talk with Petter about this.
  32. - Find out why uae.device has to be mounted manually with Kick 1.3.
  33.   The problem seems to be that we don't have a handler for it. I _think_ what
  34.   we need is the seglist of the standard filesystem handler. Problem is,
  35.   DOS hasn't been started when the devices are initialized and so we can't get
  36.   to the DosBase->RootNode->FileHandlerSeg pointer, and then there is the
  37.   confusing matter of BCPL GlobVecs and other weird stuff...
  38. - Some incompatibilities might be fixed with user-modifiable fudge variables
  39.   the same way it's done in various C64 emulators.
  40. - With the new display code, it would probably be easier than before to
  41.   implement ECS resolutions - however, a lot of places rely on the OCS timing
  42.   parameters and display sizes.
  43. - Figure out a diskfile format that supports every possible non-standard
  44.   format.
  45. - Implement 68551 MMU. I have docs now. Not among the most necessary things.
  46.   Should be done like exception 3 handling: add code to genamode in gencpu.c.
  47. - Implement AGA support. Some bits and pieces exist.
  48. - Reimplement Amiga OS. (Well-behaved) Amiga programs could then be made
  49.   to use the X Window System as a "public screen". Of course, not all the
  50.   OS would have to be re-done, only Intuition/GFX/Layers (which is enough).
  51.   [Started, look at gfxlib.c - not usable yet.]
  52. - Find some extremely clever ways to optimize the smart update methods. Some
  53.   ideas:
  54.   a) Always use memcmpy() to check for bitplane differences. If no differences
  55.      are found, see if BPLxDELAY got modified, if so, scroll.
  56.      Problems:
  57.       * You'd still have to draw a few pixels around the DIW borders. Not very
  58.         hard.
  59.       * Scrolling with memcpy in video memory can be terribly slow (no, I
  60.         shouldn't have bought the cheaper video card with DRAMs)
  61.       * At least every 15 pixels a full update has to be done since the
  62.         bitplane pointers get updated after that. And that's with the slowest
  63.     scrolling - if the playfield scrolls faster, the benefit converges
  64.     against zero.
  65.      You could also do vertical scrolling tests, but similar problems arise - 
  66.      where should one check? One line above/below? What about faster
  67.      scrolling? You could use the bitplane pointers as hints, but with
  68.      double/triple buffering this gets problematic, too.
  69.      On the whole, I don't think it would be worth the effort, even if it
  70.      works very well for a few games.
  71.   b) Well, there is no b). If I thought of something I forgot it while
  72.      writing a).
  73. - Port it to Java and Emacs Lisp
  74. - A formal proof of correctness would be nice.
  75.  
  76.  
  77. Source file layout
  78.  
  79. src/      contains (mostly) machine-independent C code.
  80. include/  contains header files included by C code.
  81. md-*/     CPU and compiler dependent files, linked to machdep by configure
  82. od-*/     operating system dependent files, linked to osdep by configure
  83. td-*/     thread library dependent files, linked to threaddep by configure
  84. sd-*/     Sound code. sd-* is only for sound systems which are not OS specific
  85.           or for which no "od-*" directory exists. Linked to sounddep
  86. targets/  Contains header files which contain some information about which
  87.           options a specific port of UAE understands.
  88.  
  89.  
  90. Coding style
  91.  
  92. As long as your code is hidden in a file buried in md-*/ or od-*/ where I
  93. never have a look at it, you can probably get away with not following these
  94. guidelines. 
  95.  
  96. * Do not include CR characters.
  97. * Do not use GNU C extensions if you can't hide them in a macro or in a
  98.   system-specific file so that an alternative implementation is available
  99.   when GNU C is not used.
  100.   This applies to _all_ OS/CPU/compiler specific details. Basically, nothing
  101.   of that sort should appear in src/*.c (we're a bit away from that goal at
  102.   the moment, but it's getting better).
  103. * Make sure your code does not make assumption about type sizes other than
  104.   the minimum widths allowed by C. If you need specific type sizes, use the
  105.   uae_u32 type and its friends.
  106. * Set up your editor so that tab characters round up to the next position
  107.   where ((cursorx-1) % 8) == 0, i.e. 8 space tabs. Do not use 4 space tabs,
  108.   that makes the code awful to read on other machines and worse to edit.
  109. * Lines can be up to 132 characters wide. Use SVGATextMode for the Linux
  110.   console, or use a windowing system in a high resolution.
  111. * C++ comments are a no-no in C code.
  112. * Indentation - look at some code in custom.c and try to follow it. Don't
  113.   use GNU 2-space-in-weird-places indentation, I find it awful. But _do_
  114.   follow the GNU rules for adding whitespace in expressions, and those for
  115.   breaking up multiple-line if statements.
  116.   Fixed indentation rules almost never make sense - break the rules if that
  117.   makes your code more readable.
  118.   Hint: Get jed from space.mit.edu, /pub/davis. It can indent your code
  119.   automatically. Put the following into your .jedrc, and it will come out
  120.   right:
  121.   C_INDENT        = 4;
  122.   C_BRACE        = 0;
  123.   C_BRA_NEWLINE        = 0;
  124.   C_Colon_Offset    = 1;
  125.   C_CONTINUED_OFFSET    = 4;
  126.  
  127.  
  128. How it works
  129.  
  130. Let's start with the memory emulation. All addressable memory is split into
  131. banks of 64K each. Each bank can define custom routines accessing bytes, 
  132. words, and longwords. All banks that really represent physical memory just 
  133. define these routines to write/read the specified amount of data to a chunk 
  134. of memory. This memory area is organized as an array of uae_u8, which means 
  135. that those parts of the emulator that want to access memory in a linear 
  136. fashion can get a (uae_u8 *) pointer and use it to circumvent the overhead of
  137. the put_*() and get_*() calls. That is done, for example, in the
  138. pfield_doline() function which handles screen refreshes.
  139. Memory banks that represent hardware registers (such as the custom chip bank
  140. at 0xDF0000) can trap reads/writes and take any necessary actions.
  141.  
  142. To provide a good emulation of graphical effects, only one thing is vital:
  143. Copper and playfield emulation have to be kept absolutely synchronous. If the
  144. copper writes to (say) a color register in a specific cycle, the playfield 
  145. hardware needs to use the new information in the next word of data it
  146. processes.
  147. UAE 0.1 used to call routines like do_pfield() and do_copper() each time the
  148. CPU emulator had finished an instruction. That was one of the reasons why it
  149. was so slow. Recent versions try to draw complete scanlines in one piece. This
  150. is possible if the copper does not write to any registers affecting the
  151. display during that scanline. Therefore, drawing the line is deferred until
  152. the last cycle of the line. However, sometimes a register which affects how
  153. the screen will look is modified before the end of the line (think of copper
  154. plasmas). That's what "struct decision thisline_decision" is for. It is
  155. initialized at the start of each line. During the line, whenever a vital
  156. register is changed, one of the decide_*() functions is called and may modify
  157. thisline_decision. There are several independent decisions:
  158.  - which DIW should be used
  159.  - where does data fetch start/stop (or is the line in the border altogether)
  160.  - where should sprites be drawn (note: the same sprite can appear more than
  161.    once on one scanline, see Turrican I world 3 levels 1 and 3 for the best
  162.    example)
  163.  - what are the playfield pointers at the start of DDF. Related, what data do
  164.    they point to.
  165.  - what are the playfield modulos at the end of DDF
  166.  - coppermagic with the colors is remembered for later use
  167.  - so is copper magic with the bitplane delay values. I used to think there
  168.    was no useful application for modifying BPLCON1 while data is being
  169.    displayed, but Sanity demos can make Amiga emulator programmers look real
  170.    old.
  171.  
  172. All of this is remembered while the raster line is processed by the hardware.
  173. After the line (at hsync), all the decisions are made if they weren't made
  174. before. At that point the line can be drawn by playfield_draw_line.
  175. Additionally, all the decisions from the previous displayed frame are saved
  176. and compared with the new ones, since often lines are not modified between
  177. frames. This saves a lot of redrawing work.
  178.  
  179. The CPU emulator no longer has to call all sorts of functions after each
  180. instruction. Instead, it keeps a list of events that are scheduled (timer
  181. interrupts, hsync and vsync events) and their "arrival time". Only the time
  182. for the next event is checked after each CPU instruction. If it's higher than
  183. the current cycle counter, the CPU can continue to execute.
  184.  
  185. Things that can't be supported with the current "decision" model:
  186.   - Changes in lores/hires mode during one line. Dunno whether that was ever
  187.     used in reality.
  188.   - Changes to the bitplane DMA bit during one line. Hardly useful and not
  189.     likely to be used. [but there are at least two programs which do ugly
  190.     things like that, and there are some hacks in UAE that make those programs
  191.     work (Magic 12 Ray of Hope 2 is one of these demos)]
  192.   - Changes in bitplane data during one line. If programs do this kind of
  193.     thing, it's most likely accidental and the program is broken. Can happen
  194.     with programs that use the blitter incorrectly, like all the Andromeda
  195.     demos.
  196.   - others? (fill in if you can think of anything)
  197.  
  198. All in all, it's unlikely that this causes compatibility problems. If it does,
  199. fudge values could be introduced (although that sort of thing gets messy
  200. quickly).
  201.  
  202.  
  203. * Native code vs. 68k code
  204.  
  205. It is possible to call native code from 68k code; autoconf.c has some routines
  206. which make setting up a call trap very easy. However, it is not as easy to
  207. call 68k code from native C code, at least not while Amiga Exec multitasking
  208. is running. You ask why?
  209.  
  210. Amiga process1 calls native function foo
  211. Native function foo calls some 68k function and goes into 68k mode
  212. Amiga context switch happens, process1 is put to sleep and process2 gets run.
  213. Amiga process2 calls native function foo
  214. Native function foo calls some 68k function and goes into 68k mode
  215. Amiga context switch happens, process2 is put to sleep and process1 gets run.
  216. Process 1 completes the 68k function called by foo and returns from 68k mode.
  217.  
  218. There. Now we are in function foo again. When it called the 68k code, process2
  219. was active. Now process1 is active, and the function we called in process2
  220. hasn't completed yet. What a mess.
  221.  
  222. To get around this, you need to do some stack magic. Code to do this exists,
  223. but it must be adapted for each port, since setting up a different stack is
  224. completely non-portable.
  225.  
  226.  
  227. * How multithreading in filesys.c works
  228.  
  229. AmigaOS is nice enough to start one processes for each mounted filesystem. All
  230. of these run in the 68k emulation code, i.e. in the main UAE thread. This is
  231. the reason why multithreading is desirable: if the main UAE thread blocks
  232. waiting for I/O, the CPU emulation can't continue to run. Since the Amiga OS
  233. is capable of multi-tasking, it is possible that other code could run until
  234. the I/O operation is complete. The most important bit of code that can run is
  235. the code that moves the mouse pointer - it's unpleasant if the pointer does
  236. not follow mouse movement during disk/CD accesses.
  237.  
  238. When a packet is received by the filesys.asm code, filesys_handler is called.
  239. This function always runs in the main UAE thread.
  240.  - In the single-threaded case, this function performs the action that was
  241.    requested, then returns 0 to indicate "action completed, reply packet".
  242.    Nothing else is performed.
  243.  - In the multi-threaded case, filesys_handler figures out which unit the
  244.    packet was for and sends the packet to the UAE thread responsible for
  245.    handling this unit. filesys_handler returns 0 to indicate: queue the
  246.    packet. Also, one (at that point unused) field in the packet is set to
  247.    0 to indicate that the action was not completed.
  248.  
  249. The latter case is the interesting one. The thread that got the packet does
  250. the following:
  251.  - perform the action as usual
  252.  - set the "command complete" field in the packet to -1.
  253.  - send a message to the AmigaOS (!) filesystem process. However, it can't do
  254.    that without some effort. We can't call 68k code from the emulator easily.
  255.    So we have to use an Amiga interrupt. The filesystem init code sets up an
  256.    Exec IntServer for the EXTER interrupt, and hsync_handler() checks
  257.    periodically whether the filesystem needs an interrupt and raises one if
  258.    necessary.
  259.    Only one dummy message is used per filesystem unit, which is allocated at
  260.    startup. This means that there must be some locking to prevent the unit
  261.    thread from sending the same message twice to the same port. To determine
  262.    whether the message is free, three counts are kept. "cmds_sent" is
  263.    incremented by the UAE thread whenever it has completed a command.
  264.    "cmds_acked" is set to the same value of cmds_sent at the point that the
  265.    interrupt handler got invoked and decided it must send a message. Finally,
  266.    cmds_complete is set to this value at the time the AmigaOS process receives
  267.    the dummy message. Whenever cmds_acked == cmds_complete, the dummy message
  268.    is free to be sent again.
  269.    
  270. The EXTER interrupt basically walks through the units, looks at the cmds_*
  271. fields and sends the dummy message to the Amiga filesystem process when
  272. possible and necessary.
  273.  
  274. When the Amiga filesystem process receives such a dummy message, it does the
  275. following:
  276.  - increment cmds_complete as described above.
  277.  - walk through the queue of unprocessed commands and see which ones now have
  278.    a status of -1, indicating that they are finished. These are removed from
  279.    the queue and replied to.
  280.  
  281.  
  282. * Calltraps at fixed locations
  283.  
  284. F0FF00: return from 68k mode.
  285. F0FF10: must have gotten lost somewhere ;)
  286. F0FF20: used by filesys.c to store away some information from the startup
  287.         packet.
  288. F0FF30: filesys_handler().
  289. F0FF40: startup_handler(), handles only the startup packet for each
  290.         filesystem.
  291. F0FF50: used by the EXTER interrupt which we set up for the filesystem.
  292. F0FF60: used by the uaectrl/uae-control programs (see uaelib.c)
  293. F0FF70: used by the task that gets set up for the mouse emulation.
  294.  
  295. * How the compiler works
  296.  
  297. .. yet to be written. To be decided, in fact.
  298.  
  299.  
  300. Portability
  301.  
  302. This section was out of date. I'll rewrite it.
  303. Some day.
  304.